package com.kyrie.lib_sys.rocketMQ.Consumer;

import com.kyrie.lib_sys.rocketMQ.Producer.MessageProducerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.Collections;

/**
 * mq缓存消费者---删除缓存
 *
 * @author heefM
 * @date 2025-09-05
 */
@Service
@RocketMQMessageListener(
        topic = "CACHE_DELETE_TOPIC",//消费监听的主题
        consumerGroup = "CACHE_DELETE_GROUP",//消费者所在的组
        selectorExpression = "CACHE_DELETE_TAG"//消费监听的二级标签
)
@Slf4j
public class CacheDeleteConsumer implements RocketMQListener<String> {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private MessageProducerService messageProducerService;

    /**
     * 消费者监听处理
     *
     * @param cacheKey
     */
//    @Override
//    public void onMessage(String cacheKey) {
//        try {
//            Boolean result = redisTemplate.delete(cacheKey);
//            if (Boolean.TRUE.equals(result)) {
//                log.info("MQ消费者删除缓存成功，key: {}", cacheKey);
//            } else {
//                log.warn("MQ消费者删除缓存失败（Key不存在），key: {}", cacheKey);
//            }
//        } catch (Exception e) {
//            log.error("MQ消费者删除缓存异常，key: {}", cacheKey, e);
//            // 直接抛出异常，让RocketMQ自动处理重试和死信队列
//            throw new RuntimeException("删除缓存失败: " + cacheKey, e);
//
//            // 添加重试机制和死信队列处理---mq默认自动重试16次数---且抛异常会自动丢入死信队列
//            //handleRetryAndDLQ(cacheKey, e);
//        }
//    }
    @Override
    public void onMessage(String cacheKey) {
        try {
            // 使用Lua脚本保证原子性操作
            // 定义Lua脚本，用于在Redis中原子性地检查并删除key
            String luaScript =
                    "if redis.call('get', KEYS[1]) ~= false then " +  // 如果key存在（get返回值不为false）
                            "   return redis.call('del', KEYS[1]) " +         // 执行删除操作，返回删除结果（1表示成功）
                            "else " +                                         // 否则（key不存在）
                            "   return 0 " +                                  // 返回0表示未执行删除
                            "end";                                            // Lua脚本结束

            // 执行Redis Lua脚本
            Long result = redisTemplate.execute(
                    // 创建RedisScript对象，指定脚本内容和返回类型为Long
                    new DefaultRedisScript<>(luaScript, Long.class),
                    // 传递参数列表，这里只传递一个参数：cacheKey
                    Collections.singletonList(cacheKey)
            );

            // 判断执行结果
            if (result == 1) {
                // 如果返回1，表示成功删除了存在的key
                log.info("MQ消费者删除缓存成功，key: {}", cacheKey);
            } else {
                // 如果返回0，表示key不存在或已经被删除，跳过处理
                log.info("MQ消费者删除缓存跳过（Key不存在或已删除），key: {}", cacheKey);
            }
        } catch (Exception e) {
            // 捕获执行过程中可能出现的任何异常
            log.error("MQ消费者删除缓存异常，key: {}", cacheKey, e);
            // 抛出运行时异常，让RocketMQ进行重试处理
            throw new RuntimeException("删除缓存失败: " + cacheKey, e);
        }
    }





    /**
     * 处理消息重试和死信队列逻辑
     *
     * @param cacheKey  缓存键
     * @param exception 异常信息
     */
    private void handleRetryAndDLQ(String cacheKey, Exception exception) {
        // 示例：记录失败次数到Redis或数据库中
        String retryCountKey = "retry_count:" + cacheKey;
        try {
            Long retryCount = redisTemplate.opsForValue().increment(retryCountKey, 1);
            if (retryCount != null && retryCount <= 3) {
                // 重试次数小于等于3次，重新发送消息到重试主题
                messageProducerService.sendCacheDeleteMessage(cacheKey);
                log.info("消息已重新发送至重试队列，key: {}, 重试次数: {}", cacheKey, retryCount);
            } else {
                // 超过最大重试次数，发送到死信队列-(简单的丢入一个主题,并不是死信队列)
                messageProducerService.sendSyncMessage("DLQ_TOPIC", cacheKey);
                log.error("消息已移至死信队列，key: {}", cacheKey);
                // 清除重试计数
                redisTemplate.delete(retryCountKey);
            }
        } catch (Exception ex) {
            log.error("处理重试和死信队列时发生异常，key: {}", cacheKey, ex);
        }
    }


}